package org.microframework.cloud.logs.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import org.microframework.base.core.util.IpUtil;
import org.microframework.base.core.web.page.PageQuery;
import org.microframework.cloud.logs.model.domain.LoginLog;
import org.microframework.cloud.logs.model.dto.LoginLogDTO;
import org.microframework.cloud.logs.service.ILoginLogService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Page;
import com.jfinal.plugin.activerecord.Record;
import eu.bitwalker.useragentutils.UserAgent;

/**
 * 登录日志服务实现
 * 
 * @author microclouds
 * @version 1.0.0
 * @date 2024-05-21
 */
@Service
public class LoginLogServiceImpl implements ILoginLogService {

    private static final Logger log = LoggerFactory.getLogger(LoginLogServiceImpl.class);

    /**
     * 记录登录成功日志
     */
    @Async
    @Override
    public boolean recordLoginSuccess(String username, String ipAddress, String userAgent) {
        try {
            LoginLog loginLog = createLoginLog(username, ipAddress, userAgent);
            loginLog.setStatus(0); // 成功状态
            loginLog.setMessage("登录成功");
            return loginLog.save();
        } catch (Exception e) {
            log.error("记录登录成功日志异常", e);
            return false;
        }
    }

    /**
     * 记录登录失败日志
     */
    @Async
    @Override
    public boolean recordLoginFailure(String username, String message, String ipAddress, String userAgent) {
        try {
            LoginLog loginLog = createLoginLog(username, ipAddress, userAgent);
            loginLog.setStatus(1); // 失败状态
            loginLog.setMessage(message);
            return loginLog.save();
        } catch (Exception e) {
            log.error("记录登录失败日志异常", e);
            return false;
        }
    }

    /**
     * 创建登录日志对象
     */
    private LoginLog createLoginLog(String username, String ipAddress, String userAgent) {
        // 解析User-Agent信息
        UserAgent ua = UserAgent.parseUserAgentString(userAgent);
        
        // 创建日志对象
        LoginLog loginLog = new LoginLog();
        loginLog.setId(UUID.randomUUID().toString());
        loginLog.setUsername(username);
        loginLog.setIpAddress(ipAddress);
        loginLog.setLoginLocation(getIpLocation(ipAddress));
        loginLog.setBrowser(ua.getBrowser().getName());
        loginLog.setOs(ua.getOperatingSystem().getName());
        loginLog.setLoginTime(new Date());
        loginLog.setCreateTime(new Date());
        
        return loginLog;
    }
    
    /**
     * 获取IP地址所在地区
     * 
     * @param ip IP地址
     * @return 地区名称
     */
    private String getIpLocation(String ip) {
        if (IpUtil.isUnknown(ip)) {
            return "未知";
        }
        
        if ("127.0.0.1".equals(ip) || "0:0:0:0:0:0:0:1".equals(ip)) {
            return "本地";
        }
        
        if (IpUtil.internalIp(ip)) {
            return "内网";
        }
        
        return "未知位置";
    }

    /**
     * 查询登录日志列表
     */
    @Override
    public Page<LoginLogDTO> selectLoginLogList(PageQuery<LoginLog> pageQuery) {
        try {
            StringBuilder sqlBuilder = new StringBuilder("FROM " + LoginLog.TABLE_NAME + " WHERE 1=1");
            List<Object> params = new ArrayList<>();
            
            LoginLog query = pageQuery.getQuery();
            if (query != null) {
                // 构建查询条件
                if (StringUtils.hasText(query.getUsername())) {
                    sqlBuilder.append(" AND username LIKE ?");
                    params.add("%" + query.getUsername() + "%");
                }
                
                if (StringUtils.hasText(query.getIpAddress())) {
                    sqlBuilder.append(" AND ip_address LIKE ?");
                    params.add("%" + query.getIpAddress() + "%");
                }
                
                if (query.getStatus() != null) {
                    sqlBuilder.append(" AND status = ?");
                    params.add(query.getStatus());
                }
            }
            
            // 设置排序
            String orderBy = StringUtils.hasText(pageQuery.getOrderBy()) ? 
                    pageQuery.getOrderBy() : "login_time";
            String orderDirection = StringUtils.hasText(pageQuery.getOrderDirection()) ? 
                    pageQuery.getOrderDirection() : "desc";
            sqlBuilder.append(" ORDER BY " + orderBy + " " + orderDirection);
            
            // 执行分页查询
            Page<Record> page = Db.paginate(
                    pageQuery.getPageNumber(), 
                    pageQuery.getPageSize(), 
                    "SELECT *", 
                    sqlBuilder.toString(), 
                    params.toArray());
            
            // 转换查询结果
            List<LoginLogDTO> list = new ArrayList<>();
            for (Record record : page.getList()) {
                LoginLog log = new LoginLog().put(record);
                list.add(convertToLoginLogDTO(log));
            }
            
            return new Page<>(list, page.getPageNumber(), page.getPageSize(), page.getTotalPage(), page.getTotalRow());
        } catch (Exception e) {
            log.error("查询登录日志异常", e);
            return new Page<>(new ArrayList<>(), 1, 10, 0, 0);
        }
    }

    /**
     * 清空登录日志
     */
    @Override
    public boolean cleanLoginLog() {
        try {
            return Db.update("TRUNCATE TABLE " + LoginLog.TABLE_NAME) > 0;
        } catch (Exception e) {
            log.error("清空登录日志异常", e);
            return false;
        }
    }

    /**
     * 删除登录日志
     */
    @Override
    public int deleteLoginLogByIds(String ids) {
        try {
            if (!StringUtils.hasText(ids)) {
                return 0;
            }
            
            String[] idArray = ids.split(",");
            StringBuilder sqlBuilder = new StringBuilder("DELETE FROM " + LoginLog.TABLE_NAME + " WHERE id IN (");
            for (int i = 0; i < idArray.length; i++) {
                if (i > 0) {
                    sqlBuilder.append(",");
                }
                sqlBuilder.append("?");
            }
            sqlBuilder.append(")");
            
            return Db.update(sqlBuilder.toString(), (Object[]) idArray);
        } catch (Exception e) {
            log.error("删除登录日志异常", e);
            return 0;
        }
    }

    /**
     * 获取登录日志详情
     */
    @Override
    public LoginLogDTO selectLoginLogById(String id) {
        try {
            LoginLog log = LoginLog.dao.findById(id);
            return log != null ? convertToLoginLogDTO(log) : null;
        } catch (Exception e) {
            log.error("查询登录日志详情异常", e);
            return null;
        }
    }

    /**
     * 导出登录日志
     */
    @Override
    public Object exportLoginLog(LoginLogDTO loginLog) {
        try {
            StringBuilder sqlBuilder = new StringBuilder("FROM " + LoginLog.TABLE_NAME + " WHERE 1=1");
            List<Object> params = new ArrayList<>();
            
            // 构建查询条件
            if (StringUtils.hasText(loginLog.getUsername())) {
                sqlBuilder.append(" AND username LIKE ?");
                params.add("%" + loginLog.getUsername() + "%");
            }
            
            if (StringUtils.hasText(loginLog.getIpAddress())) {
                sqlBuilder.append(" AND ip_address LIKE ?");
                params.add("%" + loginLog.getIpAddress() + "%");
            }
            
            if (loginLog.getStatus() != null) {
                sqlBuilder.append(" AND status = ?");
                params.add(loginLog.getStatus());
            }
            
            // 设置排序
            sqlBuilder.append(" ORDER BY login_time DESC");
            
            // 执行查询
            List<Record> records = Db.find("SELECT * " + sqlBuilder.toString(), params.toArray());
            
            // 转换查询结果
            List<LoginLogDTO> list = new ArrayList<>();
            for (Record record : records) {
                LoginLog log = new LoginLog().put(record);
                list.add(convertToLoginLogDTO(log));
            }
            
            return list;
        } catch (Exception e) {
            log.error("导出登录日志异常", e);
            return new ArrayList<>();
        }
    }

    /**
     * 将 LoginLog 转换为 LoginLogDTO
     */
    private LoginLogDTO convertToLoginLogDTO(LoginLog log) {
        if (log == null) {
            return null;
        }
        
        LoginLogDTO dto = new LoginLogDTO();
        dto.setId(log.getId());
        dto.setUsername(log.getUsername());
        dto.setIpAddress(log.getIpAddress());
        dto.setLoginLocation(log.getLoginLocation());
        dto.setBrowser(log.getBrowser());
        dto.setOs(log.getOs());
        dto.setStatus(log.getStatus());
        dto.setMsg(log.getMessage());
        dto.setLoginTime(log.getLoginTime());
        dto.setCreateTime(log.getCreateTime());
        
        return dto;
    }
} 